package com.ruoyi.web.controller.system.util;

import com.ruoyi.system.domain.StockMainBoardDetail;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

/**
 * 精确的浮点数运算
 *
 * @author ruoyi
 */
public class DateUtil {

    /** 默认除法运算精度 */
    private static final int DEF_DIV_SCALE = 10;

    /** 这个类不能实例化 */
    private DateUtil() {
    }

    public static long calculateWorkdaysBetween(LocalDate startDate, LocalDate endDate) {
        // 确保开始日期不晚于结束日期
        if (startDate.isAfter(endDate)) {
            LocalDate temp = startDate;
            startDate = endDate;
            endDate = temp;
        }

        long totalDays = ChronoUnit.DAYS.between(startDate, endDate) + 1; // 包含开始和结束日期
        long workdays = 0;
        // 计算工作日数量（排除周末）
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            if (date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY) {
                workdays++;
            }
        }

        return workdays - 2;
    }


    /**
     * 在股票列表中查找最近连续涨停序列之前15天内的一个涨停记录
     * @param stockList 股票列表，按 day 升序排列
     * @return 符合条件的涨停记录（找到即终止），否则返回 null
     */
    public static Object[] findPreContinuousLimitUpIn15Days(List<StockMainBoardDetail> stockList) {
        if (stockList == null || stockList.isEmpty()) {
            return null;
        }

        int n = stockList.size();
        int continuousStartIndex = -1; // 连续涨停序列起始索引

        // 从后向前扫描，找到最近的连续涨停序列
        for (int i = n - 1; i >= 0; i--) {
            if (isLimitUp(stockList.get(i))) {
                // 向前追溯连续涨停的起始点
                int j = i;
                while (j >= 0 && isLimitUp(stockList.get(j))) {
                    j--;
                }
                continuousStartIndex = j + 1;
                break; // 只处理最近的序列
            }
        }

        // 如果未找到连续涨停序列，返回 null
        if (continuousStartIndex == -1) {
            return null;
        }

        // 获取连续涨停序列起始日的 day 值
        // 遍历列表，查找 day 在 [minDay, maxDay] 范围内的涨停记录
        Object[] stockArray = new Object[2];
        if(stockList.size()==1 || stockList.size() ==2){
            return null;
        }
        int startIndex = continuousStartIndex ==0 ? 0 : continuousStartIndex - 1;
        int index = 0;
        for (int i = startIndex; i >= 0; i--) {
            StockMainBoardDetail stock = stockList.get(i);
            if (isLimitUp(stock)) {
                stockArray[0] = stock;
                stockArray[1] = continuousStartIndex-1 - i;
                return stockArray; // 找到即返回
            }
            if(index>= 15){
                break;
            }
            index++;
        }

        return null; // 未找到
    }


    /**
     * 在股票列表中查找最近连续涨停序列之前15天内的一个涨停记录
     * @param stockList 股票列表，按 day 升序排列
     * @return 符合条件的涨停记录（找到即终止），否则返回 null
     */
    public static Object[] findPreContinuousLimitUpIn30Days(List<StockMainBoardDetail> stockList) {
        if (stockList == null || stockList.isEmpty()) {
            return null;
        }

        int n = stockList.size();
        int continuousStartIndex = -1; // 连续涨停序列起始索引
        int continuousEndIndex = -1;   // 连续涨停序列结束索引

        // 从后向前扫描，找到最近的连续涨停序列
        for (int i = n - 1; i >= 0; i--) {
            if (isLimitUp(stockList.get(i))) {
                continuousEndIndex = i;
                // 向前追溯连续涨停的起始点
                int j = i;
                while (j >= 0 && isLimitUp(stockList.get(j))) {
                    j--;
                }
                continuousStartIndex = j + 1;
                break; // 只处理最近的序列
            }
        }

        // 如果未找到连续涨停序列，返回 null
        if (continuousStartIndex == -1) {
            return null;
        }

        // 获取连续涨停序列起始日的 day 值
        // 遍历列表，查找 day 在 [minDay, maxDay] 范围内的涨停记录
        Object[] stockArray = new Object[2];
        if(stockList.size()==1 || stockList.size() ==2){
            return null;
        }
        int startIndex = continuousStartIndex ==0 ? 0 : continuousStartIndex - 1;
        int index = 0;
        for (int i = startIndex; i >= 0; i--) {
            StockMainBoardDetail stock = stockList.get(i);
            if (isLimitUp(stock)) {
                stockArray[0] = stock;
                stockArray[1] = continuousStartIndex-1 - i;
                return stockArray; // 找到即返回
            }
            if(index>= 30){
                break;
            }
            index++;
        }

        return null; // 未找到
    }


    /**
     * 判断单个股票记录是否涨停（基于 limitUp 字段）
     * @param stock 股票记录
     * @return true 如果涨停（涨幅 ≥9.5%）
     */
    private static boolean isLimitUp(StockMainBoardDetail stock) {
        if (stock == null || stock.getLimitUp() == null) {
            return false;
        }
        BigDecimal threshold = new BigDecimal("9.5");
        return stock.getLimitUp().compareTo(threshold) >= 0;
    }

    /**
     * 处理股票数据列表的主要方法
     * @param stockList 股票数据列表，应按交易日顺序排列（从小到大）
     * @return 找到的第一个满足条件的涨停日股票数据；如果未找到，返回null
     */
    public static Object[] processStocks(List<StockMainBoardDetail> stockList, List<String> dates) {
        if (stockList == null || stockList.isEmpty()) {
            return null;
        }

        int consecutiveLimitUpCount = 0;
        boolean foundNonLimitUpAfterConsecutive = false;
        int searchStartIndex = -1;

        // 1. 遍历列表，跳过最初的连续涨停
        for (int i = stockList.size() - 1; i >= 0; i--) {
            StockMainBoardDetail currentStock = stockList.get(i);
            if (isLimitUp(currentStock)) {
                consecutiveLimitUpCount++;
            } else {
                // 遇到非涨停日，意味着连续涨停序列结束
                if (consecutiveLimitUpCount > 0) {
                    searchStartIndex = i; // 从这个非涨停日的索引开始，后续可以寻找符合条件的涨停
                    foundNonLimitUpAfterConsecutive = true;
                }
                break; // 跳出循环，停止寻找连续涨停
            }
        }

        String twoDateFormat = "yyyy-MM-dd";
        SimpleDateFormat twoSdf = new SimpleDateFormat(twoDateFormat);
        // 2. 从连续涨停结束后的位置开始，最多检查15天（包括非涨停日和涨停日），寻找满足条件的第一个涨停
        int remainingDaysToSearch = 15;
        Object[] stockArray = new Object[2];
        for (int i = searchStartIndex; i < stockList.size() && remainingDaysToSearch > 0; i--, remainingDaysToSearch--) {
            if (i == -1) {
                return null;
            }
            StockMainBoardDetail currentStock = stockList.get(i);
            Date createTime = currentStock.getCreateTime();
            String formatDate = twoSdf.format(createTime);
            if (isLimitUp(currentStock)) {
                // 遇到涨停日，检查是否满足目标条件
                boolean b = currentStock.getLimitUp().compareTo(new BigDecimal("9.5")) >= 0;
                if (dates.contains(formatDate) && b) {
                    stockArray[0] = currentStock;
                    stockArray[1] = 15 - remainingDaysToSearch;
                    return stockArray; // 找到满足条件的涨停，返回该股票数据
                }
                if (i == 0 && !(dates.contains(formatDate) && b)) {
                    return null;
                }
                // 如果是涨停但不满足条件，则继续检查后续天数
            }
            // 如果不是涨停日，继续检查后续天数，不满足条件不会返回
            // 注意：即使在15天内遇到新的连续涨停，只要其中某一天满足条件也会返回
        }

        // 3. 如果在接下来的15天内没有找到满足条件的涨停，返回null
        return null;
    }
    // 格式化金额显示
    public static String formatMoney(double amount) {
        if (amount == 0) return "-";

        if (amount >= 100000000) {
            return String.format("¥%.2f亿", amount / 100000000);
        } else if (amount >= 10000) {
            return String.format("¥%.2f万", amount / 10000);
        } else {
            return String.format("¥%.2f", amount);
        }
    }

    /**
     * 计算股票的最大连续涨停天数
     *
     * @param stockDataList 按记录天数(day)升序排列的股票每日数据列表
     * @return 最大连续涨停天数
     */
    public static int calculateMaxContinuousLimitUpDays(List<StockMainBoardDetail> stockDataList) {
        if (stockDataList == null || stockDataList.isEmpty()) {
            return 0;
        }

        int maxContinuousDays = 0; // 最大连续天数
        int currentContinuousDays = 0; // 当前连续天数
        // 假设基准涨幅为10%，使用BigDecimal进行精确比较
        BigDecimal limitUpThreshold = new BigDecimal("9.50");

        for (int i = stockDataList.size() - 1; i >= 0; i--) {
            StockMainBoardDetail todayData = stockDataList.get(i);
            // 方法1：使用涨幅字段(limitUp)进行判断（推荐，更简单直接）
            if (todayData.getLimitUp() != null && todayData.getLimitUp().compareTo(limitUpThreshold) >= 0) {
                currentContinuousDays++;
                // 更新最大连续天数
                if (currentContinuousDays > maxContinuousDays) {
                    maxContinuousDays = currentContinuousDays;
                }
            }else{
                break;
            }

        }

        return maxContinuousDays;
    }

}
